package org.javahispano.javacup.tacticas_aceptadas.rudeboy.chimbitaFinal;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.JugadorDetalle;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;

public class Ayudativo {

	public static List<Comando> getComandosDepurado(List<Comando> listaOri) {
		boolean[] comandosGolpear = new boolean[11];
		Comando[] comandosIr= new Comando[11];
		List<Comando> ret = new ArrayList<Comando>();
		for (Comando comando : listaOri) {
			int idxUsado = comando.getIndJugador();
			if (comando instanceof ComandoGolpearBalon) {
				if(!comandosGolpear[idxUsado]){
					comandosGolpear[idxUsado] = true;
					ret.add(comando);
				}
			}else{
				ComandoIrA com = (ComandoIrA) comando;
				if (com.getIrA() != null && !Double.isNaN(com.getIrA().getX()) && !Double.isNaN(com.getIrA().getY())){
					comandosIr[idxUsado] = comando;
				}
			}
		}
		for (Comando comandoir : comandosIr) {
			if (comandoir != null){
				ret.add(comandoir);
			}
		}
		listaOri = null;
		return ret;
	}

	public static Posicion[] getLineaInterseccionArquero(Posicion balonPos) {
		double nuevoY = balonPos.distancia(Constantes.centroArcoInf) / 25;
		if (nuevoY > 1) {
			return rectaIntersecArqueroDefault;
		}
		Posicion[] ret = new Posicion[] {
				new Posicion(rectaIntersecArqueroDefault[0].getX(), Constantes.centroArcoInf.getY()
						+ (Constantes.ANCHO_AREA_CHICA * nuevoY)),
				new Posicion(rectaIntersecArqueroDefault[1].getX(), Constantes.centroArcoInf.getY()
						+ (Constantes.ANCHO_AREA_CHICA * nuevoY)), };
		return ret;
	}

	public static Posicion getPosicionArquero(Posicion balonPos, Posicion... balonposAntA) {
		Posicion balonposAnt = (balonposAntA == null || balonposAntA.length < 1) ? Constantes.centroArcoInf
				: balonposAntA[0];
		Posicion[] rectaIntersecArquero = getLineaInterseccionArquero(balonPos);
		Posicion posIdeal = Posicion.Interseccion(rectaIntersecArquero[0], rectaIntersecArquero[1], balonPos,
				balonposAnt);
		if (posIdeal == null) {
			posIdeal = Constantes.cornerInfIzq;
		}
		if ((posIdeal.getX() > rectaIntersecArquero[0].getX() || posIdeal.getX() < rectaIntersecArquero[1].getX())) {
			posIdeal = Posicion.Interseccion(rectaIntersecArquero[0], rectaIntersecArquero[1], balonPos,
					Constantes.centroArcoInf);
			if (posIdeal == null) {
				posIdeal = Constantes.cornerInfIzq;
			}
			if ((posIdeal.getX() > rectaIntersecArquero[0].getX() || posIdeal.getX() < rectaIntersecArquero[1].getX())) {
				posIdeal = Constantes.centroArcoInf.moverAngulo(Constantes.centroArcoInf.angulo(balonPos), 2.5);
			}
		}
		return posIdeal;
	}

	/**
	 * Determina cual de los jugadores dado es el portero.
	 * 
	 * @param jugadores
	 * @return
	 */
	public static int getArquero(JugadorDetalle[] jugadores) {
		for (int i = 0; i < jugadores.length; i++) {
			JugadorDetalle jugadorDetalle = jugadores[i];
			if (jugadorDetalle.esPortero()) {
				return i;
			}
		}
		return 0;
	}

	public static double obtenerFuerzaGolpe(Posicion posAc, Posicion posDes, JugadorDetalle patea) {
		/*
		 * obtener la fuerza con la que debo golpear para llevar el balon desde
		 * la posAc hasta la posDes
		 */
		double distanciaRecorrer = posAc.distancia(posDes);
		final double factor = .1188;
		double v0 = Math.sqrt(factor * distanciaRecorrer);
		double ret = v0 / Constantes.getVelocidadRemate(patea.getRemate());
		return 2 * ret;
	}

	public static double obtenerDistancia(JugadorDetalle jug, Posicion posA, Posicion posB) {
		/*
		 * calcular la distancia (en n�mero de iteraciones) que le tomar�a al
		 * jugador el llegar a la posicionB desde la posA
		 */
		double dist = posA.distancia(posB);
		return dist / jug.getVelocidad();
	}

	public static int posicionMia(Posicion pos, SituacionPartido sp) {
		int mioCerca = pos.indiceMasCercano(sp.misJugadores());
		int suyoCerca = pos.indiceMasCercano(sp.rivales());
		double it = obtenerDistancia(sp.detalleMisJugadores()[mioCerca], sp.misJugadores()[mioCerca], pos);
		double cercanoSuyo = obtenerDistancia(sp.detalleJugadoresRivales()[suyoCerca], sp.rivales()[suyoCerca], pos);
		if (it <= cercanoSuyo) {
			return mioCerca;
		}
		return -1;
	}

	public static int rivalesCercanos(Posicion pos, SituacionPartido sp) {
		Posicion[] rivales = sp.rivales();
		int ret = 0;
		for (Posicion posicion : rivales) {
			if (posicion.distancia(pos) < 13d) {
				ret++;
			}
		}
		return ret;
	}

	public static Posicion getPosicionDisparo(Posicion balon, Posicion arqRival) {
		if (balon.getY() < arqRival.getY()) {
			double mCentro = getPendiente(balon, Constantes.centroArcoSup);
			double mPortero = getPendiente(balon, arqRival);
			if (mCentro == mPortero) {
				return Constantes.centroArcoSup;
			}
			if (mCentro > mPortero) {
				return PUNTO_DISPARO_DER;
			}
			return PUNTO_DISPARO_IZQ;
		}
		return Constantes.centroArcoSup;

	}

	public static Comando dispararAlArco(int jugador, Posicion porteroRival, SituacionPartido sp) {
		Posicion p = getPosicionDisparo(sp.balon(), porteroRival);
		// Posicion p = Constantes.centroArcoSup;
		Comando ret = null;
		double remate = sp.detalleMisJugadores()[jugador].getRemate();
		double xMedios = sp.balon().distancia(p) - 4d;
		double y = 3.23d;
		double angulo = Math.atan(2 * y / xMedios);
		double velocidad = Math.sqrt(2 * y * Constantes.G) / Math.sin(angulo);
		if (velocidad <= Constantes.getVelocidadRemate(remate) + 0.1d) {
			velocidad = velocidad / Constantes.getVelocidadRemate(remate);
			ret = new ComandoGolpearBalon(jugador, p, velocidad, angulo * 180 / Math.PI);
		} else {
			ret = new ComandoGolpearBalon(jugador, p, 1, 26.7d - (sp.balon().distancia(p) * 0.24d));
		}
		return ret;
	}

	/**
	 * predice el movimiento de una trayectoria en 3 dimensiones
	 * 
	 * @param posVie
	 * @param posAct
	 * @param iteraciones:
	 *            predecir la posicion en este numero de iteraciones, -1 para
	 *            predecirla hasta que la pelota este controlable
	 * @return
	 */
	public static Posicion3D getSiguientePuntoEnTrayectoria(Posicion3D posVie, Posicion3D posAct, int iteraciones) {
		if (posVie == null || posVie.pos2d.distancia(posAct.pos2d) < 0.4) {
			return posAct;
		}
		double deltaX = posAct.pos2d.getX() - posVie.pos2d.getX();
		double deltaY = posAct.pos2d.getY() - posVie.pos2d.getY();
		double velocidad = posAct.altura > 0d ? Constantes.FACTOR_DISMINUCION_VEL_BALON_AIRE
				: Constantes.FACTOR_DISMINUCION_VEL_BALON_SUELO;
		Posicion proximaPos2D = posAct.pos2d.moverPosicion(deltaX * velocidad, deltaY * velocidad);
		double proximaAltura = 0;
		if (posAct.altura > 0d) {
			double dist = posAct.pos2d.distancia(proximaPos2D);
			double deltaZ = posAct.altura - posVie.altura;
			velocidad = Math.sqrt(deltaZ * deltaZ + dist * dist) * Constantes.FACTOR_DISMINUCION_VEL_BALON_AIRE;
			double angVert = Math.atan(deltaZ / dist);
			deltaZ = Math.round(velocidad * Math.sin(angVert) / Constantes.G) * Constantes.G;
			proximaAltura = Math.round((posAct.altura + deltaZ - Constantes.G) / Constantes.G) * Constantes.G;
		}
		Posicion3D ret = new Posicion3D(proximaPos2D.setDentroCampoJuego(), proximaAltura);
		if (iteraciones > 1) {
			return getSiguientePuntoEnTrayectoria(posAct, ret, iteraciones - 1);
		}
		if (iteraciones < 0 && proximaAltura > Constantes.ALTURA_CONTROL_BALON) {
			return getSiguientePuntoEnTrayectoria(posAct, ret, iteraciones - 1);
		}
		return ret;
	}

	private static double getPendiente(Posicion p1, Posicion p2) {
		if (p2.getX() - p1.getX() == 0) {
			return 0;
		}
		return (p2.getY() - p1.getY()) / (p1.getX() - p2.getX());
	}

	public static final Posicion D = new Posicion(-19.020979020979023, -17.015837104072398);
	public static final Posicion E = new Posicion(12.601398601398602, -17.352941176470589);
	public static final Posicion F = new Posicion(-18.202797202797203, 13.065610859728507);
	public static final Posicion G = new Posicion(18.685314685314687, 14.490950226244346);

	public static final Posicion H = new Posicion(0, Constantes.penalSup.getY() - Constantes.ANCHO_AREA_CHICA);
	public static final Posicion HR = new Posicion(Constantes.LARGO_AREA_CHICA / 2, Constantes.penalSup.getY());
	public static final Posicion HL = new Posicion(Constantes.LARGO_AREA_CHICA / -2, Constantes.penalSup.getY());

	public static final Posicion I = new Posicion(0, -14.490950226244346);
	public static final Posicion J = new Posicion(0, 14.490950226244346);

	public static final Posicion PUNTO_DISPARO_IZQ = new Posicion(Constantes.centroArcoSup.getX() - 2,
			Constantes.posteIzqArcoSup.getY());
	public static final Posicion PUNTO_DISPARO_DER = new Posicion(Constantes.centroArcoSup.getX() + 2,
			Constantes.posteDerArcoSup.getY());
	private static Posicion[] rectaIntersecArqueroDefault = new Posicion[] {
			new Posicion(Constantes.centroArcoInf.getX() + (Constantes.LARGO_ARCO / 2), Constantes.centroArcoInf.getY()
					+ Constantes.ANCHO_AREA_CHICA),
			new Posicion(Constantes.centroArcoInf.getX() - (Constantes.LARGO_ARCO / 2), Constantes.centroArcoInf.getY()
					+ Constantes.ANCHO_AREA_CHICA) };

}
